from sqlalchemy import and_
from sqlalchemy.exc import IntegrityError
from app import db
from app.models import User
import hashlib
from app.util.jwt_tool import generate_token
import logging
from app.enums.enums import RoleEnum, UserStatusEnum
from app import redis_client
from datetime import datetime

from app.util.log_utils import add_log_event

# 配置日志记录器
logger = logging.getLogger(__name__)


class UserService:
    """
    用户服务类，处理所有用户相关的业务逻辑
    """

    @staticmethod
    def register(username, password, role):
        """
        用户注册
        Args:
            username: 用户名
            password: 密码
            role: 用户角色
        Returns:
            tuple: (是否成功, 错误信息)
        """
        logger.info(f"开始注册新用户: {username}")
        md5 = hashlib.md5()
        md5.update(password.encode('utf-8'))

        new_user = User(
            username=username,
            password=md5.hexdigest(),
            identity=int(role),
        )
        try:
            db.session.add(new_user)
            db.session.commit()
            logger.info(f"用户 {username} 注册成功")
            return True, None
        except IntegrityError:
            logger.warning(f"用户 {username} 注册失败: 用户名已存在")
            return False, "注册失败,用户名已存在"
        except Exception as e:
            logger.error(f"用户 {username} 注册失败: {str(e)}")
            return False, "注册失败"

    @staticmethod
    def login(username, password):
        """
        用户登录
        Args:
            username: 用户名
            password: 密码
        Returns:
            tuple: (是否成功, 错误信息, 用户数据)
        """
        logger.info(f"用户 {username} 尝试登录")
        md5 = hashlib.md5()
        md5.update(password.encode('utf-8'))
        user = User.query.filter_by(username=username).first()

        if user is None:
            logger.warning(f"用户 {username} 登录失败: 用户不存在")
            return False, "用户不存在", None
        if user.password != md5.hexdigest():
            logger.warning(f"用户 {username} 登录失败: 密码错误")
            return False, "密码错误", None
        if user.status == UserStatusEnum.LOCKED.value:
            logger.warning(f"用户 {username} 登录失败: 用户被锁定")
            return False, "用户被锁定", None

        logger.info(f"用户 {username} 登录成功")
        return True, None, {
            'id': user.id,
            'token': generate_token(user.id, user.username, user.identity),
            'role': user.identity,
            'avatar': user.avatar,
        }

    @staticmethod
    def get_user_info(user_id):
        """
        获取用户信息
        Args:
            user_id: 用户ID
        Returns:
            tuple: (是否成功, 错误信息, 用户数据)
        """
        logger.info(f"获取用户信息: user_id={user_id}")
        user = User.query.filter_by(id=user_id).first()
        if user is None:
            logger.warning(f"获取用户信息失败: 用户不存在, user_id={user_id}")
            return False, "用户不存在", None
        if user.status == UserStatusEnum.LOCKED.value:
            logger.warning(f"获取用户信息失败: 用户被锁定, user_id={user_id}")
            return False, "用户被锁定", None

        logger.info(f"成功获取用户信息: user_id={user_id}")
        return True, None, {
            'id': user.id,
            'username': user.username,
            'age': user.age,
            'gender': user.gender,
            'phone': user.phone,
            'email': user.email,
            'avatar': user.avatar,
            'description': user.description,
            'role': user.identity
        }

    @staticmethod
    def update_user_info(user_id, update_data):
        """
        更新用户信息
        Args:
            user_id: 用户ID
            update_data: 更新数据
        Returns:
            tuple: (是否成功, 错误信息)
        """
        logger.info(f"开始更新用户信息: user_id={user_id}")
        user = User.query.filter_by(id=user_id).first()
        if user is None:
            logger.warning(f"更新用户信息失败: 用户不存在, user_id={user_id}")
            return False, "用户不存在"
        if user.status == UserStatusEnum.LOCKED.value:
            logger.warning(f"更新用户信息失败: 用户被锁定, user_id={user_id}")
            return False, "用户被锁定"
        if User.query.filter(
                and_(User.username == update_data['username'], User.id != user_id)).first() is not None:
            logger.warning(f"更新用户信息失败: 用户名已存在, user_id={user_id}")
            return False, "用户名已存在"
        # 更新信息
        user.username = update_data['username']
        user.age = update_data['age']
        user.gender = update_data['gender']
        user.phone = update_data['phone']
        user.email = update_data['email']
        user.avatar = update_data['avatar']
        user.description = update_data['description']

        try:
            db.session.commit()
            logger.info(f"用户信息更新成功: user_id={user_id}")
            return True, None
        except Exception as e:
            db.session.rollback()
            logger.error(f"用户信息更新失败: {str(e)}, user_id={user_id}")
            add_log_event("更新用户信息出现错误",f"用户{user_id}信息更新失败: {str(e)}")
            return False, "更新失败"

    @staticmethod
    def update_password(user_id, old_password, new_password):
        """
        更新用户密码
        Args:
            user_id: 用户ID
            old_password: 旧密码
            new_password: 新密码
        Returns:
            tuple: (是否成功, 错误信息)
        """
        logger.info(f"开始更新用户密码: user_id={user_id}")
        # 获取旧密码MD5加密值
        md5 = hashlib.md5()
        md5.update(old_password.encode('utf-8'))
        old_password_hash = md5.hexdigest()

        user = User.query.filter_by(id=user_id, password=old_password_hash).first()
        if user is None:
            logger.warning(f"更新密码失败: 原密码错误, user_id={user_id}")
            return False, "原密码错误"
        if user.status == UserStatusEnum.LOCKED.value:
            logger.warning(f"更新密码失败: 用户被锁定, user_id={user_id}")
            return False, "用户被锁定"
        # 对新密码进行md5加密
        md5 = hashlib.md5()
        md5.update(new_password.encode('utf-8'))
        user.password = md5.hexdigest()

        try:
            db.session.commit()
            logger.info(f"用户密码更新成功: user_id={user_id}")
            return True, None
        except Exception as e:
            db.session.rollback()
            logger.error(f"用户密码更新失败: {str(e)}, user_id={user_id}")
            add_log_event("用户更新密码出现错误",f"用户{user_id}密码更新失败: {str(e)}")
            return False, "密码更新失败"

    @staticmethod
    def get_user_avatar(user_id):
        """
        获取用户头像
        Args:
            user_id: 用户ID
        Returns:
            tuple: (是否成功, 错误信息, 头像数据)
        """
        logger.info(f"获取用户头像: user_id={user_id}")
        user = User.query.filter_by(id=user_id).first()
        if user is None:
            logger.warning(f"获取用户头像失败: 用户不存在, user_id={user_id}")
            return False, "用户不存在", None

        logger.info(f"成功获取用户头像: user_id={user_id}")
        return True, None, {
            'avatar': user.avatar,
            'role': user.identity
        }

    @staticmethod
    def check_admin(uid):
        """
        检查用户是否为管理员
        Args:
            uid: 用户ID
        Returns
            是否为管理员
        """
        logger.info(f"检查用户是否为管理员: uid={uid}")
        user = User.query.filter_by(id=uid).first()
        if user is None:
            logger.warning(f"检查用户是否为管理员失败: 用户不存在, uid={uid}")
            return False
        if user.identity == RoleEnum.ADMIN.value:
            logger.info(f"用户是管理员: uid={uid}")
            return True
        logger.info(f"用户不是管理员: uid={uid}")
        return False

    @staticmethod
    def get_admin_list(uid, page, size):
        """
        获取管理员列表
        :param uid: 用户id
        :param page: 第几页
        :param size: 几条数据
        :return:
            tuple:(是否成功,信息,返回的数据）
        """
        logger.info(f"管理员{uid}获取管理员列表: page={page}, size={size}")
        if not UserService.check_admin(uid):
            logger.warning(f"获取管理员列表失败: 权限不足, uid={uid}")
            return False, "权限不足", None
        user_list = User.query.filter_by(identity=RoleEnum.ADMIN.value).paginate(page=page, per_page=size, error_out=False)
        return True, None, {
            'total': user_list.total,
            'list': [{
                'id': user.id,
                'username': user.username,
                'phone': user.phone,
                'email': user.email,
                'avatar': user.avatar,
                'status': user.status,
                'age': user.age,
                'gender': user.gender,
                'createTime': str(user.create_time),
                'updateTime': str(user.update_time)
            } for user in user_list.items]
        }

    @staticmethod
    def toggle_admin_status(uid, user_id, status):
        """
        切换管理员状态接口
        :param uid: 发起切换请求的管理员
        :param user_id: 切换状态的管理员
        :param status: 要切换的状态
        :return:
            tuple:(是否成功,信息)
        """
        logger.info(f"{uid}切换管理员状态: user_id={user_id}, status={status}")
        if status not in [UserStatusEnum.LOCKED.value, UserStatusEnum.NORMAL.value]:
            logger.warning(f"切换管理员状态失败: 状态错误, uid={uid}")
            return False, "状态错误"
        if UserService.is_super_admin(user_id):
            logger.warning(f"切换管理员状态失败: 不能修改超级管理员的状态, uid={uid}")
            return False, "不能修改超级管理员的状态"
        if not UserService.is_super_admin(uid):
            logger.warning(f"切换管理员状态失败: 只有超级管理员可以修改其他管理员的状态, uid={uid}")
            return False, "只有超级管理员可以修改其他管理员的状态"

        user = User.query.filter_by(id=user_id).first()

        if user is None:
            logger.warning(f"切换管理员状态失败: 用户不存在, uid={uid}")
            return False, "用户不存在"
        if user.identity != RoleEnum.ADMIN.value:
            logger.warning(f"切换管理员状态失败: 该用户不是管理员, uid={uid}")
            return False, "修改异常"
        user.status = status
        try:
            db.session.commit()
            logger.info(f"管理员状态切换成功: user_id={user_id}, status={status}")
            add_log_event("切换管理员状态", f"超级管理员修改{user_id}的状态为"+"锁定" if status==0 else "正常","info")
            return True, None
        except Exception as e:
            db.session.rollback()
            logger.error(f"管理员状态切换失败: {str(e)}, user_id={user_id}, status={status}")
            return False, "修改失败"

    @staticmethod
    def delete_admin(uid, user_id):
        """
        删除管理员接口
        :param uid: 发起请求的管理员id
        :param user_id: 要删除的管理员id
        :return:
            tuple:(是否成功,信息)
        """
        if UserService.is_super_admin(user_id):
            logger.warning(f"删除管理员失败: 不能删除超级管理员, uid={uid}")
            return False, "不能删除超级管理员"
        if not UserService.is_super_admin(uid):
            logger.warning(f"删除管理员失败: 只有超级管理员才可以删除管理员, uid={uid}")
            return False, "只有超级管理员才可以删除管理员"

        user = User.query.filter_by(id=user_id).first()
        if user is None:
            logger.warning(f"删除管理员失败: 用户不存在, uid={uid}")
            return False, "用户不存在"
        if user.identity != 1:
            logger.warning(f"删除管理员失败: 该用户不是管理员, uid={uid}")
            return False, "修改异常"
        try:
            db.session.delete(user)
            db.session.commit()
            logger.info(f"删除管理员成功: user_id={user_id}")
            add_log_event("删除管理员", f"超级管理员删除了管理员{user_id}","info")
            return True, None
        except Exception as e:
            db.session.rollback()
            logger.error(f"删除管理员失败: {str(e)}, user_id={user_id}")
            return False, "修改失败"

    @staticmethod
    def is_super_admin(uid):
        """
        判断是否是超级管理员接口
        :param uid: 用户id
        :return:
            bool: 是否是超级管理员
        """
        user = User.query.filter_by(id=uid).first()
        if user is None:
            logger.warning(f"判断是否是超级管理员失败: 用户不存在, uid={uid}")
            return False
        if user.identity == RoleEnum.ADMIN.value and user.id == '1':
            logger.info(f"用户是超级管理员: uid={uid}")
            return True
        logger.info(f"用户不是超级管理员: uid={uid}")
        return False

    @staticmethod
    def add_admin(uid, username, password):
        """
        添加管理员接口
        :param uid: 发起请求的管理员id
        :param username: 用户名
        :param password: 密码
        :return:
            tuple:(是否成功,信息)
        """
        logger.info(f"添加管理员: uid={uid}, username={username}, password={password}")
        if username is None or password is None:
            logger.warning(f"添加管理员失败: 参数错误, uid={uid}")
            return False, "参数错误"
        if not UserService.check_admin(uid):
            logger.warning(f"添加管理员失败: 权限不足, uid={uid}")
            return False, "权限不足"
        if User.query.filter_by(username=username).first() is not None:
            logger.warning(f"添加管理员失败: 用户名已存在, uid={uid}")
            return False, "用户名已存在"
        md5= hashlib.md5()
        md5.update(password.encode('utf-8'))
        password = md5.hexdigest()
        user = User(username=username, password=password, identity=RoleEnum.ADMIN.value)
        try:
            db.session.add(user)
            db.session.commit()
            logger.info(f"添加管理员成功: uid={uid}, username={username}")
            add_log_event("添加管理员",  f"超级管理员添加了管理员{user.id}","info")
            return True, None
        except Exception as e:
            db.session.rollback()
            logger.error(f"添加管理员失败: {str(e)}, uid={uid}, username={username}")
            return False, "添加失败"




